// ProjectTemplate.cpp : Defines the entry point for the application.
//
#include "Renderer.h"
#include "Application.h"

#include "ProjectTemplate.h"

using namespace std;


// renderer initialized in main file
extern Renderer *g_renderer;

const float			FOG_DISTANCE = 50;
const float			BG_COLOR[] = {0, 0, 0, 1};


//
// @brief	Main entry
//
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	// Init app config
	AppConfig config;
	config.appName = "ProjectTemplate";
	config.cmdShow = nCmdShow;
	config.width = 1200;
	config.height = 800;
	config.hInstance = hInstance;
	
	// Init scene
	ProjectTemplate viewer;
	config.scene = &viewer;

	// Start application
	return Application::GetInstance()->Process( config );
}


ProjectTemplate::ProjectTemplate()
{
}

ProjectTemplate::~ProjectTemplate()
{
}

// Handle keyboard and mouse input
bool ProjectTemplate::HandleMessage( UINT msg, WPARAM wParam, LPARAM lParam )
{
	bool handled = true;

	switch( msg )
	{
	case WM_KEYDOWN:
		switch( wParam )
		{	
			case VK_SPACE:
				m_camera.Reset();
				break;
			default:
				handled = false;
				break;
		}
		break;
	default:
		handled = false;
		break;
	};

	// Default key and mouse handler
	if ( !handled )
		return Scene::HandleMessage( msg, wParam, lParam );

	return true;
}

// Init the scene
bool ProjectTemplate::Init()
{
	Scene::Init();
	
	int width = m_screen_width;
	int height = m_screen_height;

	// Setup render specific stuff
	{
		// Setup viewport and projection matrix
		glViewport( 0, 0, width, height );

		glMatrixMode( GL_PROJECTION );
		glLoadIdentity();
		m_camera.glPerspective( width, height );

		// Other OpenGL flags
		glEnable(GL_DEPTH_TEST);				// Depthtest
		glDepthFunc(GL_LESS);
		//glEnable(GL_CULL_FACE);					// Cull face
		//glEnable(GL_BLEND);						// Blending
		//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glShadeModel(GL_SMOOTH);				// Shading
	}

	// FOG
	{
//		glEnable(GL_FOG);
		glFogf( GL_FOG_END, FOG_DISTANCE );
		glFogi( GL_FOG_MODE, GL_LINEAR);
		glFogfv( GL_FOG_COLOR, BG_COLOR );
	}

	// Setup lighting
	{
//		glEnable(GL_LIGHTING);

		float lightPos[]		= { 0.f, 0.f, 10.f, 1.0f };
		float lightAmbient[]	= { 0.2f, 0.2f, 0.2f, 1.0f };
		float lightDiffuse[]	= { 0.7f, 0.7f, 0.7f, 1.0f };
		glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
		glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
		glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
		glEnable(GL_LIGHT0);

		// Setup material
		glEnable(GL_COLOR_MATERIAL);
		glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

		// Set specular and shiniess
		float shininess = 15.0f;
		float specularColor[4] = {0.7, 0.7, 0.7, 1.f};
		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); // range 0 ~ 128
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor);
	}


	// Hud Text
	m_HUD_text.push_back( "Keys" );
	m_HUD_text.push_back( "  SPACE: Reset Camera" );


	/********************************************
				 Init objects here
	********************************************/

	return true;
}

void ProjectTemplate::UnInit()
{
	/********************************************
				 UnInit objects here
	********************************************/

	Scene::UnInit();
}

void ProjectTemplate::Update()
{
	Scene::Update();

	/********************************************
				 Update objects here
	********************************************/
}

void ProjectTemplate::Render( Renderer* renderer )
{
	// Clear back buffer
	glClearColor( BG_COLOR[0], BG_COLOR[1], BG_COLOR[2], BG_COLOR[3] );
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;

	// Setup view matrix
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
	m_camera.glLookAt();

	// HUD
	RenderHUD( renderer, 0.6, 0.855, m_HUD_text );

	// Axis
	DrawAxis();


	/********************************************
				 Render objects here
	********************************************/
}
